/*
Copyright 2011 Mohit Shah
    
This file is part of SoundBlogs.

SoundBlogs is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

SoundBlogs is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with SoundBlogs.  If not, see <http://www.gnu.org/licenses/>.
*/

package com.application.soundblogs;

import android.app.Activity;
import android.app.Dialog;
import android.content.Intent;
import android.content.res.Resources;
import android.graphics.drawable.Drawable;
import android.media.MediaPlayer;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import java.util.ArrayList;
import java.util.Date;
import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.text.DateFormat;

import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.util.ByteArrayBuffer;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.osmdroid.ResourceProxy;
import org.osmdroid.api.IGeoPoint;
import org.osmdroid.util.GeoPoint;
import org.osmdroid.views.MapView;
import org.osmdroid.views.overlay.ItemizedIconOverlay;
import org.osmdroid.views.overlay.ItemizedOverlayWithFocus;
import org.osmdroid.views.overlay.OverlayItem;


import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.Window;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.RelativeLayout.LayoutParams;
import android.widget.TextView;
import android.widget.Toast;

public class SearchMap extends Activity {

	// ===========================================================
	// Constants
	// ===========================================================

	private static final int MENU_ZOOMIN_ID = Menu.FIRST;
	private static final int MENU_ZOOMOUT_ID = MENU_ZOOMIN_ID + 1;
	private static final int NEXT_ID = MENU_ZOOMOUT_ID +1;

	// ===========================================================
	// Fields
	// ===========================================================

	private MapView mOsmv;
	private ItemizedOverlayWithFocus<OverlayItem> mMyLocationOverlay;
	private ResourceProxy mResourceProxy;
	private static final String INIT = "init";
	private static final String EVENTS = "events";
	private static final String KEYWORD = "keyword";
	private String LogTag = "JSON-DATA";
	private OverlayItem one,two,three = null;
	private String json_text = null;
	private int number;
	private String keyword = null;
	private JSONArray array = null;
	private JSONObject object,inner_object, inner_object1, inner_object2, inner_object3;
	private int[] keyword_match = new int[3];
	private int center;
	private int latCenter, lonCenter;
	private Dialog dialog;
	private String[] tag1 = new String[3];
	private String[] tag2 = new String[3];
	private String[] tag3 = new String[3];
	private String[] time = new String[3];
	private String[] audio = new String[3];
	private String[] path = new String[3];
	private int last_tap;
	private MediaPlayer mPlayer=null;
	Button listen_button;
	private boolean isPlaying=false;
	private AsyncTask<Void,Integer,Void> playaudio, downloadaudio = null;
	// ===========================================================
	// Constructors
	// ===========================================================
	/** Called when the activity is first created. */
	@Override
	public void onCreate(final Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
        requestWindowFeature(Window.FEATURE_CUSTOM_TITLE);
        getWindow().setFeatureInt(Window.FEATURE_CUSTOM_TITLE, R.layout.mytitle);
		mResourceProxy = new ResourceProxyImpl(getApplicationContext());
		Bundle extras = getIntent().getExtras();
		json_text = new String(extras.getString(EVENTS));
		number = extras.getInt(INIT);
		keyword = new String(extras.getString(KEYWORD));
		Log.d("JSON-DATA",json_text);
		Log.d("MAP NUMBER",Integer.toString(number));
		final RelativeLayout rl = new RelativeLayout(this);
		try {
		array = new JSONArray(json_text);
		object = array.getJSONObject(number);
		Log.d(LogTag,object.toString());
		inner_object = object.getJSONObject("inner");
		Log.d(LogTag,inner_object.toString());
		inner_object1 = inner_object.getJSONObject("inner1");
		Log.d(LogTag,inner_object1.toString());
		inner_object2 = inner_object.getJSONObject("inner2");
		Log.d(LogTag,inner_object2.toString());
		inner_object3 = inner_object.getJSONObject("inner3");
		Log.d(LogTag,inner_object3.toString());		
		String check_tag1 = new String(inner_object1.getString("tag1"));
		tag1[0] = new String(check_tag1);
		String check_tag2 = new String(inner_object1.getString("tag2"));
		tag2[0] = new String(check_tag2);
		String check_tag3 = new String(inner_object1.getString("tag3"));
		tag3[0] = new String(check_tag3);
		time[0] = new String(inner_object1.getString("time"));
		audio[0] = new String("http://soundblogs.org/audio/"+inner_object1.getString("source"));
		path[0] = new String("/sdcard/"+inner_object1.getString("source"));
		Log.d("AUDIO_SOURCE",audio[0]);
		if(keyword.equals(check_tag1)||keyword.equals(check_tag2)||keyword.equals(check_tag3)){
			keyword_match[0] = 1;
			center = 0;
		}
		else {
			keyword_match[0] = 0;
		}
		check_tag1 = new String(inner_object2.getString("tag1")); 
		tag1[1] = new String(check_tag1);
		check_tag2 = new String(inner_object2.getString("tag2"));
		tag2[1] = new String(check_tag2);
		check_tag3 = new String(inner_object2.getString("tag3"));
		tag3[1] = new String(check_tag3);
		time[1] = new String(inner_object2.getString("time"));
		audio[1] = new String("http://soundblogs.org/audio/"+inner_object2.getString("source"));
		path[1] = new String("/sdcard/"+inner_object2.getString("source"));		
		if(keyword.equals(check_tag1)||keyword.equals(check_tag2)||keyword.equals(check_tag3)){
			keyword_match[1] = 1;
			center = 1;
		}
		else {
			keyword_match[1] = 0;
		}
		check_tag1 = new String(inner_object3.getString("tag1")); 
		tag1[2] = new String(check_tag1);
		check_tag2 = new String(inner_object3.getString("tag2"));
		tag2[2] = new String(check_tag2);
		check_tag3 = new String(inner_object3.getString("tag3"));
		tag3[2] = new String(check_tag3);
		time[2] = new String(inner_object3.getString("time"));
		audio[2] = new String("http://soundblogs.org/audio/"+inner_object3.getString("source"));
		path[2] = new String("/sdcard/"+inner_object3.getString("source"));		
		if(keyword.equals(check_tag1)||keyword.equals(check_tag2)||keyword.equals(check_tag3)){
			keyword_match[2] = 1;
			center = 2;
		}
		else {
			keyword_match[2] = 0;
		}

		this.mOsmv = new MapView(this, 256);
		if(center==0) {
			latCenter = (int) (Double.parseDouble(inner_object1.getString("lat"))*1000000);
			lonCenter = (int) (Double.parseDouble(inner_object1.getString("lon"))*1000000);
		}
		else if(center==1) {
			latCenter = (int) (Double.parseDouble(inner_object2.getString("lat"))*1000000);
			lonCenter = (int) (Double.parseDouble(inner_object2.getString("lon"))*1000000);
		}
		else {
			latCenter = (int) (Double.parseDouble(inner_object3.getString("lat"))*1000000);
			lonCenter = (int) (Double.parseDouble(inner_object3.getString("lon"))*1000000);
		}
		this.mOsmv.getController().setCenter(new GeoPoint(latCenter,lonCenter));
		this.mOsmv.getController().setZoom(15);
		this.mOsmv.getController().animateTo(new GeoPoint(latCenter,lonCenter));
		rl.addView(this.mOsmv, new RelativeLayout.LayoutParams(LayoutParams.FILL_PARENT,
				LayoutParams.FILL_PARENT));
		/* Itemized Overlay */
		
			/* Create a static ItemizedOverlay showing a some Markers on some cities. */
			final ArrayList<OverlayItem> items = new ArrayList<OverlayItem>();
			one = new OverlayItem(object.getString("city")+","+object.getString("date"), 
					inner_object1.getString("desc"), 
					new GeoPoint((int)(Double.parseDouble(inner_object1.getString("lat"))*1000000),
								(int)(Double.parseDouble(inner_object1.getString("lon"))*1000000)));
			if(keyword_match[0]==1) {
				one.setMarker(getResources().getDrawable(R.drawable.marker_default));
			}
			else {
				one.setMarker(getResources().getDrawable(R.drawable.marker_alternate));				
			}
			two = new OverlayItem(object.getString("city")+","+object.getString("date"), 
					inner_object2.getString("desc"), 
					new GeoPoint((int)(Double.parseDouble(inner_object2.getString("lat"))*1000000),
								(int)(Double.parseDouble(inner_object2.getString("lon"))*1000000)));
			if(keyword_match[1]==1) {
				two.setMarker(getResources().getDrawable(R.drawable.marker_default));
			}
			else {
				two.setMarker(getResources().getDrawable(R.drawable.marker_alternate));				
			}
			three = new OverlayItem(object.getString("city")+","+object.getString("date"), 
					inner_object3.getString("desc"), 
					new GeoPoint((int)(Double.parseDouble(inner_object3.getString("lat"))*1000000),
								(int)(Double.parseDouble(inner_object3.getString("lon"))*1000000)));
			if(keyword_match[2]==1) {
				three.setMarker(getResources().getDrawable(R.drawable.marker_default));
			}
			else {
				three.setMarker(getResources().getDrawable(R.drawable.marker_alternate));				
			}
			items.add(one);
			items.add(two);
			items.add(three);
			/* OnTapListener for the Markers, shows a simple Toast. */
			this.mMyLocationOverlay = new ItemizedOverlayWithFocus<OverlayItem>(items,
					new ItemizedIconOverlay.OnItemGestureListener<OverlayItem>() {
						@Override
						public boolean onItemSingleTapUp(final int index, final OverlayItem item) {
							dialog = new Dialog(SearchMap.this);
							dialog.setContentView(R.layout.overlay_dialog);
							dialog.getWindow().setLayout(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT); 
							dialog.setTitle(item.getTitle());
							TextView snippet = (TextView) dialog.findViewById(R.id.snippet);
							snippet.setText(item.getSnippet());
							TextView Tag1 = (TextView) dialog.findViewById(R.id.tag1);
							Tag1.setText(tag1[index]);
							TextView Tag2 = (TextView) dialog.findViewById(R.id.tag2);
							Tag2.setText(tag2[index]);
							TextView Tag3 = (TextView) dialog.findViewById(R.id.tag3);
							Tag3.setText(tag3[index]);
							TextView Time = (TextView) dialog.findViewById(R.id.time);
							Time.setText(time[index]);
							listen_button = (Button) dialog.findViewById(R.id.listen_button);
							listen_button.setOnClickListener(new audio_play());
							last_tap = index;
							dialog.show();
							return true;							
						}

						@Override
						public boolean onItemLongPress(final int index, final OverlayItem item) {
							Toast.makeText(
									SearchMap.this,
									"Item '" + item.mTitle + "' (index=" + index
											+ ") got long pressed", Toast.LENGTH_LONG).show();
							return false;
						}
					}, mResourceProxy);
			this.mMyLocationOverlay.setFocusItemsOnTap(false);
			//this.mMyLocationOverlay.setFocusedItem(0);

			this.mOsmv.getOverlays().add(this.mMyLocationOverlay);
			final ImageView ivZoomIn = new ImageView(this);
			ivZoomIn.setImageResource(R.drawable.zoom_in);
			/* Create RelativeLayoutParams, that position in in the top right corner. */
			final RelativeLayout.LayoutParams zoominParams = new RelativeLayout.LayoutParams(
					RelativeLayout.LayoutParams.WRAP_CONTENT,
					RelativeLayout.LayoutParams.WRAP_CONTENT);
			zoominParams.addRule(RelativeLayout.ALIGN_PARENT_RIGHT);
			zoominParams.addRule(RelativeLayout.ALIGN_PARENT_TOP);
			rl.addView(ivZoomIn, zoominParams);

			ivZoomIn.setOnClickListener(new zoom_in()); 

			/* Create a ImageView with a zoomOut-Icon. */
			final ImageView ivZoomOut = new ImageView(this);
			ivZoomOut.setImageResource(R.drawable.zoom_out);

			/* Create RelativeLayoutParams, that position in in the top left corner. */
			final RelativeLayout.LayoutParams zoomoutParams = new RelativeLayout.LayoutParams(
					RelativeLayout.LayoutParams.WRAP_CONTENT,
					RelativeLayout.LayoutParams.WRAP_CONTENT);
			zoomoutParams.addRule(RelativeLayout.ALIGN_PARENT_LEFT);
			zoomoutParams.addRule(RelativeLayout.ALIGN_PARENT_TOP);
			rl.addView(ivZoomOut, zoomoutParams);

			ivZoomOut.setOnClickListener(new zoom_out()); 

		this.setContentView(rl);
		}
		catch (JSONException j) {
			Log.d("OverlayError","JSON Failure");
		}
		downloadaudio = new DownloadAudio().execute();
	}
	private class zoom_in implements View.OnClickListener{
		@Override
		public void onClick(final View v) {
			SearchMap.this.mOsmv.getController().zoomIn();
		}
	};
	private class zoom_out implements View.OnClickListener {
		@Override
		public void onClick(final View v) {
			SearchMap.this.mOsmv.getController().zoomOut();
		}
	};
    private void downloadFile(String url, String path) {
    	HttpURLConnection ucon;
    	try {
            URL location = new URL(url);
            File file = new File(path);

            long startTime = System.currentTimeMillis();
            Log.d("AudioDownload", "download begining");
            Log.d("AudioDownload", "download url:" + url);
            Log.d("AudioDownload", "downloaded file name:" + path);
            /* Open a connection to that URL. */
            ucon = (HttpURLConnection) location.openConnection();

            /*
             * Define InputStreams to read from the URLConnection.
             */
            InputStream is = ucon.getInputStream();
            BufferedInputStream bis = new BufferedInputStream(is);

            /*
             * Read bytes to the Buffer until there is nothing more to read(-1).
             */
            ByteArrayBuffer baf = new ByteArrayBuffer(50);
            int current = 0;
            while ((current = bis.read()) != -1) {
                    baf.append((byte) current);
            }

            /* Convert the Bytes read to a String. */
            FileOutputStream fos = new FileOutputStream(file);
            fos.write(baf.toByteArray());
            fos.close();
            Log.d("AudioDownload", "download ready in"
                            + ((System.currentTimeMillis() - startTime) / 1000)
                            + " sec");

    } catch (IOException e) {
            Log.d("A", "Error: " + e);
    }

}    	
    
	private void downloadAllFiles(String[] audio, String[] path) {
		downloadFile(audio[0],path[0]);
		downloadFile(audio[1],path[1]);
		downloadFile(audio[2],path[2]);
	}
	private class audio_play implements View.OnClickListener {
		@Override
		public void onClick(View v) {
			if(!isPlaying) {
			Toast.makeText(getApplicationContext(), "Playing Audio...", Toast.LENGTH_LONG).show();
			listen_button.setText("          Stop          ");
			isPlaying=true;
			playaudio = new PlayAudio().execute();
			}
			else {
				mPlayer.release();
				mPlayer=null;
				isPlaying=false;
				listen_button.setText("Revisit the Experience!");
			}
		}
	};
    private class PlayAudio extends AsyncTask<Void,Integer,Void> {
    	@Override
    	public Void doInBackground(Void... params){
    		Void ret = null;
			mPlayer = new MediaPlayer();
			Uri.Builder b = Uri.parse(path[last_tap]).buildUpon();
    		String url = b.build().toString();
    		Log.d("AudioPlayer",url);
    		try {
				mPlayer.setDataSource(url);					
				mPlayer.prepare();
				mPlayer.start();
    		}
    		catch (IOException e) {
    			Log.e("AudioPlayer", "prepare() failed");
    		}
    		return ret;
    	}
    }
    private class DownloadAudio extends AsyncTask<Void,Integer,Void> {
    	@Override
    	public Void doInBackground(Void... params){
    		Void ret = null;
    		downloadAllFiles(audio,path);
    		return ret;
    	}
    }


	@Override
	public boolean onCreateOptionsMenu(final Menu pMenu) {
		pMenu.add(0, MENU_ZOOMIN_ID, Menu.NONE, "ZoomIn");
		pMenu.add(0, MENU_ZOOMOUT_ID, Menu.NONE, "ZoomOut");
		pMenu.add(0, NEXT_ID, Menu.NONE, "Next");
		return true;
	}

	@Override
	public boolean onMenuItemSelected(final int featureId, final MenuItem item) {
		switch (item.getItemId()) {
		case MENU_ZOOMIN_ID:
			this.mOsmv.getController().zoomIn();
			return true;

		case MENU_ZOOMOUT_ID:
			this.mOsmv.getController().zoomOut();
			return true;
		case NEXT_ID:
			Intent intent = new Intent(SearchMap.this,SearchMap.class);
			intent.putExtra(KEYWORD,keyword);
			intent.putExtra(EVENTS, json_text);
			intent.putExtra(INIT, (number+1)%3);
			SearchMap.this.startActivity(intent);
			SearchMap.this.finish();
		}
		return false;
	}

	// ===========================================================
	// Methods
	// ===========================================================

	// ===========================================================
	// Inner and Anonymous Classes
	// ===========================================================
}
